﻿#pragma once

/// @addtogroup helpers
/// @{
///		@defgroup helpers_varargs 可变参数辅助工具集
///		包含了可变参数传递，存储，转换等实用功能。
///		@{
///			@defgroup helpers_varargs_examples 使用例子
///			包含了可变参数传递，存储，转换等实用功能的具体使用案例。
///		@}
/// @}


#include <boost/any.hpp>

#if RL_VARARGS_ENABLE_EXCEPTIONS && defined(__EXCEPTIONS) ||_HAS_EXCEPTIONS > 0
#	include <exception>
#endif

/// @addtogroup helpers_varargs
/// @{

namespace helpers {

	/// 可变参数集合类
	class VarArgs
	{
	public:
		enum { MinIndex = 0, MaxIndex = 8, MaxCount }; ///< 定义索引常数

#if 0
//		typedef boost::any Argument; ///< 定义参数类型
		typedef Any Argument;
#else
		class Argument : public boost::any 
		{
		public:
			template<typename ValueType>
			Argument(const ValueType & value)
				: boost::any(value)
			{}
			Argument()
				: boost::any()
			{};

			Argument(const Argument& other)
				: boost::any(static_cast<const boost::any&>(other))
			{

			}

			template<typename ValueType>
			Argument& operator=(const ValueType& other)
			{
				boost::any::operator=(other);
				return *this;
			}

			Argument& operator=(const Argument& other)
			{
				boost::any::operator=(static_cast<const boost::any&>(other));
				return *this;
			}

		public:
			template<typename T>
			operator T() const
			{
				(boost::any) *this;
				return boost::any_cast<T>(*this);
			}

			template<typename T>
			operator T()
			{
				return boost::any_cast<T>(*this);
			}
		};
#endif

	public:
		VarArgs()
		{
		}
		
		VarArgs(const Argument& a0)
		{
			init(a0);
		}
		
		VarArgs(const Argument& a0, const Argument& a1)
		{
			init(a0, a1);
		}
		
		VarArgs(const Argument& a0, const Argument& a1, const Argument& a2)
		{
			init(a0, a1, a2);
		}
		
		VarArgs(const Argument& a0, const Argument& a1, const Argument& a2, const Argument& a3)
		{
			init(a0, a1, a2, a3);
		}
		
		VarArgs(const Argument& a0, const Argument& a1, const Argument& a2, const Argument& a3, const Argument& a4)
		{
			init(a0, a1, a2, a3, a4);
		}
		
		VarArgs(const Argument& a0, const Argument& a1, const Argument& a2, const Argument& a3, const Argument& a4, const Argument& a5)
		{
			init(a0, a1, a2, a3, a4, a5);
		}
		
		VarArgs(const Argument& a0, const Argument& a1, const Argument& a2, const Argument& a3, const Argument& a4, const Argument& a5, const Argument& a6)
		{
			init(a0, a1, a2, a3, a4, a5, a6);
		}
		
		VarArgs(const Argument& a0, const Argument& a1, const Argument& a2, const Argument& a3, const Argument& a4, const Argument& a5, const Argument& a6, const Argument& a7)
		{
			init(a0, a1, a2, a3, a4, a5, a6, a7);
		}
		VarArgs(const Argument& a0, const Argument& a1, const Argument& a2, const Argument& a3, const Argument& a4, const Argument& a5, const Argument& a6, const Argument& a7, const Argument& a8)
		{
			init(a0, a1, a2, a3, a4, a5, a6, a7, a8);
		}
		
		~VarArgs()
		{
		}
		
	public:
		/// 获取指定索引的参数内容.
		/// @param index 参数索引位置.
		/// @return 返回指定索引所对应的内容.
		/// @par 参考示例:
		/// 以下代码演示了此函数的一些使用方式及功用.
		/// @code
		///    ...
		///    int a = 100;
		///    double b = 3.1415926;
		///    const char_t* c = "Hello, varriable arguments";
		///    VarArgs va1(a, b, c);
		///    ...
		///    int use_a = va1.get<int>(0);
		///    double use_b = va1.get<dobule>(1);
		///    const char_t* use_c = va1.get<const char_t*>(2);
		///    ...
		/// @endcode
		template <typename T>
		T get(size_t index) const throw()
		{
			throw_error(index);
			return boost::any_cast<T>(_args[index]);
		//	return static_cast<T>(_args[index]);
		}

		/// 设定指定索引的参数内容.
		/// @param index 参数索引位置.
		/// @return 无.
		/// @code
		///    ...
		///    int a = 100;
		///    double b = 3.1415926;
		///    const char_t* c = "Hello, varriable arguments";
		///    VarArgs va1(a, b, c);
		///    ...
		///    va1.set(0, 200);
		///    va1.set(1, 3.1415926 * 2);
		///    const char_t* cc = "Goodbye, varriable arguments";
		///    va1.set(2, cc);
		///    ...
		/// @endcode
		template <typename T>
		void set(size_t index, T val)
		{
			throw_error(index);
			_args[index] = val;
		}

		const Argument& operator[](size_t index) const
		{
			throw_error(index);
			return this->_args[index];
		}

		Argument& operator[](size_t index)
		{
			throw_error(index);
			return this->_args[index];
		}

	protected:
		void init()
		{
		}
		
		void init(const Argument& a0)
		{
			_args[0] = a0;
		}
		
		void init(const Argument& a0, const Argument& a1)
		{
			init(a0);
			_args[1] = a1;	
		}
		
		void init(const Argument& a0, const Argument& a1, const Argument& a2)
		{
			init(a0, a1);
			_args[2] = a2;
		}
		
		void init(const Argument& a0, const Argument& a1, const Argument& a2, const Argument& a3)
		{
			init(a0, a1, a2);
			_args[3] =  a3;
		}
		
		void init(const Argument& a0, const Argument& a1, const Argument& a2, const Argument& a3, const Argument& a4)
		{
			init(a0, a1, a2, a3);
			_args[4] = a4;
		}
		
		void init(const Argument& a0, const Argument& a1, const Argument& a2, const Argument& a3, const Argument& a4, const Argument& a5)
		{
			init(a0, a1, a2, a3, a4);
			_args[5] = a5;
		}
		
		void init(const Argument& a0, const Argument& a1, const Argument& a2, const Argument& a3, const Argument& a4, const Argument& a5, const Argument& a6)
		{
			init(a0, a1, a2, a3, a4, a5);
			_args[6] = a6;
		}
		
		void init(const Argument& a0, const Argument& a1, const Argument& a2, const Argument& a3, const Argument& a4, const Argument& a5, const Argument& a6, const Argument& a7)
		{
			init(a0, a1, a2, a3, a4, a5, a6);
			_args[7] = a7;
		}

		void init(const Argument& a0, const Argument& a1, const Argument& a2, const Argument& a3, const Argument& a4, const Argument& a5, const Argument& a6, const Argument& a7, const Argument a8)
		{
			init(a0, a1, a2, a3, a4, a5, a6, a7);
			_args[8] = a8;
		}

	private:
		/// 拷贝构造函数.
		/// 定义为私有成员, 禁止拷贝构造.
		VarArgs(const VarArgs&)
		{
			// Nothing to do.
		}
		
		/// 赋值复制函数.
		/// 定义为私有成员, 禁止赋值复制。
		VarArgs& operator =(const VarArgs&)
		{
			return *this;
		}
		
		/// 检查参数, 在需要时抛出异常.
		/// @param index 参数索引号
		/// @return 无
		void throw_error(size_t index) 
		{
			static_cast<const VarArgs&>(*this).throw_error(index);

		}

		void throw_error(size_t index) const
		{
#if RL_VARARGS_ENABLE_EXCEPTIONS && defined(__EXCEPTIONS) || _HAS_EXCEPTIONS > 0
			if (index > MaxIndex)
				throw std::exception("Out of range");
#endif
		}


	private:
		Argument _args[MaxCount]; ///< 参数列表, TODO: 此列表尚待优化，以解决参数很少的情况下占用空间过多的问题.
	}; // class VarArgs

} // namespace helper

/// @}


/// @addtogroup helpers_varargs_examples
/// @{
/// @section 可变参数集合类用例
/// @code
/// #include <iostream>
/// #include "boost/ref.hpp"
/// #include "VarArgs.hpp"
///
/// using boost::ref;
/// using boost::cref;
/// using boost::reference_wrapper;
///
/// class tracker
/// {
/// public:
///	    tracker()
///	    {
///         std::cout << "tracker().\n";
///	    }
///     tracker(const tracker& rhs)
///     {
///         std::cout << "tracker(const tracker& rhs).\n";
///	    }
///	    ~tracker()
///	    {
///         std::cout << "~tracker().\n";
///	    }
/// };
///
/// void test(const VarArgs& va)
/// {
///     std::cout << "A0: " << va.get<int>(0) << std::endl;
///     std::cout << "A1: " << va.get<const char_t *>(1) << std::endl;
///     std::cout << "A2: " << va.get<tstring>(2) << std::endl;
///     std::cout << "A3: " << va.get<double>(3) << std::endl;
///     tracker& trk = va.get< reference_wrapper<tracker> >(4);
///     std::cout << "sizeof(trk): " << sizeof(trk) << std::endl;
/// }
///
/// int main(int argc, char_t** argv)
/// {
///     tstring s = "string object";
///     tracker tracker;
///     test(VarArgs(1, static_cast<const char_t*>(NDVR_TEXT("literal characters")), s, 3.1515926, ref(tracker)));
///     return 0;
/// }
/// @endcode
/// @}
